#pragma once
#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <set>
#include "Log.hpp"
#include "ip_net_address.hpp"

// 处理命令
class Command
{
public:
    Command()
    {
        _safe_command.emplace("ls");
        _safe_command.emplace("touch");
    }
    bool SafeCheck()
    {
        for (auto s : _safe_command)
        {
            if (strncmp(_command.c_str(), s.c_str(), s.size()) == 0)
                return true;
        }
        return false;
    }
    std::string Execute()
    {
        if (!SafeCheck())
        {
            return "command errer";
        }
        FILE *fp = popen(_command.c_str(), "r");
        if (fp)
        {
            std::string result;
            char line[1024] = {0};
            while (fgets(line, sizeof(line), fp)) // 获取一行包含了\n\0
            {
                result += line;
                // memset(line, 0, sizeof(line)); // 重置一下
            }
            pclose(fp);
            return result.empty() ? "command success" : result;
        }
        LOG(FATAL, "popen fail");
        return "popen fail";
    }
    void HandlerCommand(int re_fd, InetAdress addr)
    {   
        //长服务
        while (1)
        {
            // 读
            char buffer[1024] = {0};
            ssize_t n = recv(re_fd, buffer, sizeof(buffer), 0);
            if (n > 0)
            {
                LOG(INFO, "recv success, client:[%s]", addr.Str().c_str());
                _command = buffer; // 注意赋值
                // Execute
                std::string result = Execute();
                // 写
                n = send(re_fd, result.c_str(), result.size(), 0);
                if (n < 0)
                {
                    LOG(FATAL, "send fail");
                    exit(-1);
                }
                LOG(INFO, "send success");
            }
            else if (n == 0)
            {
                LOG(INFO, "client exit");
                break;
            }
            else
            {
                LOG(FATAL, "recv fail");
                exit(-1);
            }
        }
    }

private:
    std::string _command;
    std::set<std::string> _safe_command;
};